﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Common.CommonModel;
using Core;
using AutoRegistDependency.Attributes;
using Repository.Base;

namespace Services.Base
{
    [Component]
    public class BaseService<T> : IBaseService<T> where T : class, new()
    {
        private IBaseRepository<T> baseRepository;
        public BaseService(IBaseRepository<T> baseRepository)
        {
            this.baseRepository = baseRepository;
        }
        public virtual ResponseModel Delete(T entity)
        {
            return CreateResponseModel(baseRepository.Delete, entity);
        }
        public virtual ResponseModel Delete(Expression<Func<T,bool>> Exp)
        {
            return CreateResponseModel(baseRepository.Delete, Exp);
        }
        public virtual ResponseModel Delete(List<T> list)
        {
            return CreateResponseModel(baseRepository.Delete, list);
        }

        public virtual ResponseModel ExecuteSqlCommand(string sql)
        {
            return CreateResponseModel(baseRepository.ExecuteSqlCommand, sql);
        }

        public virtual ResponseModel FromSql(string sql)
        {
            return CreateResponseModel(baseRepository.FromSql, sql);
        }

        public virtual ResponseModel GetInfo(Expression<Func<T, bool>> predicate)
        {
            return CreateResponseModel(baseRepository.GetInfo, predicate);
        }

        public virtual ResponseModel GetInfoByPage(Expression<Func<T, bool>> predicate, int page, int limit)
        {
            var model = CreateResponseModel(baseRepository.GetInfoByPage, predicate, page, limit);
            return model;
        }

        public virtual ResponseModel GetInfoToDataTable(Expression<Func<T, bool>> predicate)
        {
            return CreateResponseModel(baseRepository.GetInfoToDataTable, predicate);
        }

        public virtual ResponseModel GetInfoToDataTableByPage(Expression<Func<T, bool>> predicate, int page, int limit)
        {
            return CreateResponseModel(baseRepository.GetInfoToDataTableByPage, predicate, page, limit);
        }

        public virtual ResponseModel GetOrderbyAscInfo(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderBy)
        {
            return CreateResponseModel(baseRepository.GetOrderbyAscInfo, predicate, orderBy);
        }
        public virtual ResponseModel GetOrderbyDescInfo(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderBy)
        {
            return CreateResponseModel(baseRepository.GetOrderbyDescInfo, predicate, orderBy);
        }

        public virtual ResponseModel GetOrderbyAscInfoByPage(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderBy, int page, int limit)
        {
            return CreateResponseModel(baseRepository.GetOrderbyAscInfoByPage, predicate, orderBy, page, limit);
        }
        public virtual ResponseModel GetOrderbyDescInfoByPage(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderBy, int page, int limit)
        {
            return CreateResponseModel(baseRepository.GetOrderbyDescInfoByPage, predicate, orderBy, page, limit);
        }

        public virtual ResponseModel Insert(T entity)
        {
            return CreateResponseModel(baseRepository.Insert, entity);
        }

        public virtual ResponseModel Insert(List<T> list)
        {
            return CreateResponseModel(baseRepository.Insert, list);
        }


        public virtual ResponseModel Update(T entity)
        {
            return CreateResponseModel(baseRepository.Update, entity);
        }
        public virtual ResponseModel Update(T entity, Expression<Func<T, object>> WhereExp)
        {
            return CreateResponseModel(baseRepository.Update, entity,WhereExp);
        }

        public virtual ResponseModel Update(Expression<Func<T, T>> SetColumns, Expression<Func<T, bool>> WhereExp)
        {
            return CreateResponseModel(baseRepository.Update, SetColumns, WhereExp);
        }

        public virtual ResponseModel UpdateIgnoreColumns(T entity, Expression<Func<T, object>> WhereExp, Expression<Func<T, object>> IgnoreExpress)
        {
            return CreateResponseModel(baseRepository.UpdateIgnoreColumns, entity, WhereExp, IgnoreExpress);
        }

        public virtual ResponseModel UpdateAppiontColumns(T entity, Expression<Func<T, object>> WhereExp, Expression<Func<T, object>> UpdateExpress)
        {
            return CreateResponseModel(baseRepository.UpdateAppiontColumns, entity, WhereExp, UpdateExpress);
        }

        public virtual ResponseModel Update(List<T> list)
        {
            return CreateResponseModel(baseRepository.Update, list);
        }
        #region 新增，修改，删除执行委托操作通用方法
        /// <summary>
        /// 一个参数的无返回值模型包装方法,一般用于事务批量，返回的code是操作成功类
        /// </summary>
        /// <typeparam name="P">实体</typeparam>
        /// <param name="func">委托执行的方法</param>
        /// <param name="p">参数p</param>
        /// <returns></returns>
        protected ResponseModel CreateResponseModel<P>(Action<P> func, P p)
        {
            ResponseModel res = new ResponseModel();
            func.Invoke(p);
            res.code = ResponseTypeEnum.OperationSucess;
            res.message = ResponseTypeEnum.OperationSucess;
            return res;
        }
        /// <summary>
        /// 一个参数的无返回值模型包装方法,一般用于事务批量，返回的code是操作成功类
        /// </summary>
        /// <typeparam name="P">实体1</typeparam>
        /// <typeparam name="P1">实体2</typeparam>
        /// <param name="func">委托执行的方法</param>
        /// <param name="p">实体1的实参</param>
        /// <param name="p1">实体2的实参</param>
        /// <returns></returns>
        protected ResponseModel CreateResponseModel<P, P1>(Action<P, P1> func, P p, P1 p1)
        {
            ResponseModel res = new ResponseModel();
            func.Invoke(p, p1);
            res.code = ResponseTypeEnum.OperationSucess;
            res.message = ResponseTypeEnum.OperationSucess;
            return res;
        }
        /// <summary>
        /// 返回bool类型的返回模型包装方法,一般用于操作数据库数据的方法
        /// </summary>
        /// <typeparam name="P">实体1</typeparam>
        /// <param name="func">委托执行的方法</param>
        /// <param name="p">实参1</param>
        /// <returns></returns>
        protected ResponseModel CreateResponseModel<P>(Func<P, bool> func, P p)
        {
            ResponseModel res = new ResponseModel();
            bool Success = func.Invoke(p);
            if (Success)
            {
                res.code = ResponseTypeEnum.OperationSucess;
                res.message = ResponseTypeEnum.OperationSucess;
            }
            else
            {
                res.code = ResponseTypeEnum.OperationFail;
                res.message = ResponseTypeEnum.OperationFail;
            }
            return res;
        }
        /// <summary>
        /// 构造一个执行委托返回值为bool的包装模型,一般用于操作数据库
        /// </summary>
        /// <typeparam name="P">参数1类型</typeparam>
        /// <typeparam name="P1">参数2类型</typeparam>
        /// <param name="func">执行的委托方法</param>
        /// <param name="p">实参1</param>
        /// <param name="p1">实参2</param>
        /// <returns></returns>
        protected ResponseModel CreateResponseModel<P,P1>(Func<P,P1, bool> func, P p,P1 p1)
        {
            ResponseModel res = new ResponseModel();
            bool Success = func.Invoke(p, p1);
            if (Success)
            {
                res.code = ResponseTypeEnum.OperationSucess;
                res.message = ResponseTypeEnum.OperationSucess;
            }
            else
            {
                res.code = ResponseTypeEnum.OperationFail;
                res.message = ResponseTypeEnum.OperationFail;
            }
            return res;
        }
        protected ResponseModel CreateResponseModel<P, P1, P2>(Func<P, P1, P2, bool> func, P p, P1 p1, P2 p2)
        {
            ResponseModel res = new ResponseModel();
            bool Success = func.Invoke(p, p1, p2);
            if (Success)
            {
                res.code = ResponseTypeEnum.OperationSucess;
                res.message = ResponseTypeEnum.OperationSucess;
            }
            else
            {
                res.code = ResponseTypeEnum.OperationFail;
                res.message = ResponseTypeEnum.OperationFail;
            }
            return res;
        }
        #endregion
        #region 不进行分页的的查询的委托通用方法
        /// <summary>
        /// 一个参数的包装模型返回方法
        /// </summary>
        /// <typeparam name="P">实体</typeparam>
        /// <typeparam name="PResult">返回结果</typeparam>
        /// <param name="func">执行的委托</param>
        /// <param name="p">实参</param>
        /// <returns></returns>
        protected ResponseModel CreateResponseModel<P, PResult>(Func<P, PResult> func, P p)
        {
            ResponseModel res = new ResponseModel();
            PResult obj = func.Invoke(p);
            res.code = ResponseTypeEnum.GetInfoSucess;
            res.message = ResponseTypeEnum.GetInfoSucess;
            res.model = obj;
            return res;
        }

        protected ResponseModel CreateResponseModel<P, P1, PResult>(Func<P, P1, PResult> func, P p, P1 p1)
        {
            ResponseModel res = new ResponseModel();
            PResult obj = func.Invoke(p, p1);
            res.code = ResponseTypeEnum.GetInfoSucess;
            res.message = ResponseTypeEnum.GetInfoSucess;
            res.model = obj;
            return res;
        }

        /// <summary>
        /// 执行三个参数的查询方法并将返回结果包装
        /// </summary>
        /// <typeparam name="P">参数1的类型</typeparam>
        /// <typeparam name="P1">参数2的类型</typeparam>
        /// <typeparam name="P2">参数3的类型</typeparam>
        /// <typeparam name="PResult">返回值类型</typeparam>
        /// <param name="func">委托执行的方法</param>
        /// <param name="p">实参1</param>
        /// <param name="p1">实参2</param>
        /// <param name="p2">实参3</param>
        /// <returns></returns>
        protected ResponseModel CreateResponseModel<P, P1, P2, PResult>(Func<P, P1, P2, PResult> func, P p, P1 p1, P2 p2)
        {
            ResponseModel res = new ResponseModel();
            PResult obj = func.Invoke(p, p1, p2);
            res.code = ResponseTypeEnum.GetInfoSucess;
            res.message = ResponseTypeEnum.GetInfoSucess;
            res.model = obj;
            return res;
        }


        protected ResponseModel CreateResponseModel<P, P1, P2, P3, PResult>(Func<P, P1, P2, P3, PResult> func, P p, P1 p1, P2 p2, P3 p3)
        {
            ResponseModel res = new ResponseModel();
            PResult obj = func.Invoke(p, p1, p2, p3);
            res.code = ResponseTypeEnum.GetInfoSucess;
            res.message = ResponseTypeEnum.GetInfoSucess;
            res.model = obj;
            return res;
        }
        protected ResponseModel CreateResponseModel<P, P1, P2, P3, P4, PResult>(Func<P, P1, P2, P3, P4, PResult> func, P p, P1 p1, P2 p2, P3 p3, P4 p4)
        {
            ResponseModel res = new ResponseModel();
            PResult obj = func.Invoke(p, p1, p2, p3, p4);
            res.code = ResponseTypeEnum.GetInfoSucess;
            res.message = ResponseTypeEnum.GetInfoSucess;
            res.model = obj;
            return res;
        }
        #endregion
    }
}
